<?php
namespace App\Common\Lib\Com;

use App\Common as com;
use App\Common\Lib\Com\Crontab as thisCrontab;

class Crontab extends com\Lib\LibBase {

	/**
	 * 日志回调函数，函数签名：fn( string $content )
	 * @var \Closure|null
	 */
	private \Closure|null $logCallback = null;

	/**
	 * 任务名称
	 * @var string|null
	 */
	private string|null $crontabName = null;

	/**
	 * @param string|null $crontabSid 任务sid
	 * @param int|null $lockTimeout 任务锁超时时间(指锁周期内同时只能运行一条任务)
	 */
	public function __construct( private string|null $crontabSid = null, private int|null $lockTimeout = null ) {
		parent::__construct();
	}

	/**
	 * 设置任务sid
	 * @param string|null $crontabSid
	 * @return $this
	 */
	public function setCrontabSid( string|null $crontabSid = null ):self {
		$this->crontabSid = $crontabSid;
		//
		return $this;
	}

	/**
	 * 获取任务sid
	 * @return string|null
	 */
	public function getCrontabSid():string|null {
		return $this->crontabSid;
	}

	/**
	 * 设置任务名称
	 * @param string|null $crontabName
	 * @return $this
	 */
	public function setCrontabName( string|null $crontabName = null ):self {
		$this->crontabName = $crontabName;
		//
		return $this;
	}

	/**
	 * 获取任务名称
	 * @return string|null
	 */
	public function getCrontabName(  ):string|null {
		return $this->crontabName;
	}

	/**
	 * 设置任务锁超时时间
	 * @param int|null $lockTimeout
	 * @return $this
	 */
	public function setLockTimeout( int|null $lockTimeout = null ):self {
		$this->lockTimeout = $lockTimeout;
		//
		return $this;
	}

	/**
	 * 获取任务锁超时时间
	 * @return int|null
	 */
	public function getLockTimeout():int|null {
		return $this->lockTimeout;
	}

	/**
	 * 设置日志回调函数
	 * @param \Closure|null $logCallback 函数签名：fn( string $content )
	 * @return $this
	 */
	public function setLogCallback( \Closure|null $logCallback = null ):self {
		$this->logCallback = $logCallback;
		//
		return $this;
	}

	/**
	 * 获取日志回调函数
	 * @return \Closure|null 函数签名：fn( string $content )
	 */
	public function getLogCallback():\Closure|null {
		return $this->logCallback;
	}

	/**
	 * 获取日志回调函数
	 * @param string $log 日志内容
	 * @return bool [true][必返]
	 */
	public function echoLog( string $log ):bool {
		if( $this->logCallback instanceof \Closure ){
			call_user_func_array( $this->logCallback, [
				date('Y-m-d H:i:s', time() ) . '[定时任务]' . $this->getCrontabName() . '：' . $log
			] );
		}
		//
		return true;
	}

	/**
	 * @param \Closure $fn 函数签名：fn( com\Lib\Com\Crontab $crontab )
	 * @return bool [true]执行成功 [false]执行失败
	 */
	public function call( \Closure $fn ):bool {
		$this->echoLog( '启动' );
		//
		$lock = com\Lib\Lock::make( $this->getCrontabSid() );
		if( ! $lock->lock( 3600 * 6 ) ){ // 锁6小时
			$this->echoLog( '终止执行，原因上锁失败...结束' );
			return false;
		}
		//
		try{
			//
			call_user_func_array( $fn, [ $this ] );
		} finally{
			$lock->unlock();
		}
		//
		$this->echoLog( '完成' );
		//
		return true;
	}

	// ===============================
	//
	//
	// 下面为静态方法
	//
	//
	// ===============================

	/**
	 * @param string|null $crontabSid 任务sid
	 * @param int|null $lockTimeout 任务锁超时时间(指锁周期内同时只能运行一条任务)
	 * @return $this
	 */
	public static function makeOfNew( string|null $crontabSid = null, int|null $lockTimeout = null  ):self {
	    return self::make( $crontabSid, $lockTimeout );
	}

}
